﻿using CPPEI.Coolzon.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using DT = CPPEI.Coolzon.Designtime.Metadata;

namespace CPPEI.Coolzon.Designer.Views
{
    /// <summary>
    /// 发布方案到服务的线程
    /// </summary>
    public static class PublishToServerThread
    {
        private static bool s_isRunning;
        private static Thread s_thread;

        private static string s_solutionDir;
        private static string s_targetDir;
        private static DT.Solution s_solution;

        private static Guid s_tempeSolutionId;

        private static Action<bool> s_completed;
        private static string s_trancactionId;
        private static ServiceProxy.PubServiceRef.PublishServiceClient s_pubSerClient;
        /// <summary>
        /// 开始发布
        /// </summary>
        /// <param name="solutionDir">方案所在的目录</param>
        /// <param name="solution">方案对象</param>
        /// <param name="completed">是否发布成功</param>
        public static void Start(string solutionDir, DT.Solution solution, Action<bool> completed)
        {
            if (s_isRunning)
            {
                return;
            }

            s_pubSerClient = ServiceProxy.PubServiceProxyManager.Create();

            s_completed = completed;

            s_tempeSolutionId = Guid.NewGuid();

            s_solution = solution;
            s_solutionDir = solutionDir;

            s_isRunning = true;
            s_thread = new Thread(Running);
            s_thread.Start();
        }

        public static void Stop()
        {
            if (s_isRunning && s_thread == null)
            {
                s_thread.Abort();
                s_isRunning = false;
                s_thread = null;
            }
        }

        private static void Running()
        {
            // 发布到本地的一个临时目录
            s_targetDir = Designtime.Metadata.Storage.GetSolutionDirectory(s_tempeSolutionId);

            if (Designtime.Metadata.Storage.CreateSolutionDirectory(s_tempeSolutionId))
            {
                DT.Publisher publisher = new DT.Publisher();
                if (publisher.Publish(s_solution, s_solutionDir, s_targetDir))
                {
                    // 准备发布
                    if(Prepare())
                    {
                        // 遍历文件然后进行上传
                        if (PublishDirectory(s_targetDir))
                        {
                            // 成功
                            if(Commit())
                            {
                                s_completed(true);
                            }
                        }
                        else
                        {
                            Cancel();
                            s_completed(false);
                        }
                    }
                    else
                    {
                        s_completed(false);
                    }
                }
                else
                {
                    s_completed(false);
                }

                //
                Designtime.Metadata.Storage.DeleteSolutionDirectory(s_tempeSolutionId);
            }
            else
            {
                s_completed(false);
            }

            s_isRunning = false;
            s_thread = null;
            Logger.DebugToTag(Library.LogTAG, "Thread publish solution to server finished");
        }

        private static bool PublishDirectory(string solutionDirectory)
        {
            string[] subDirectories = Directory.GetDirectories(solutionDirectory);
            for (int index = 0; index < subDirectories.Length; index++)
            {
                if (!PublishDirectory(subDirectories[index]))
                {
                    return false;
                }
            }

            string[] files = Directory.GetFiles(solutionDirectory);
            for (int index = 0; index < files.Length; index++)
            {
                PublishFile(files[index]);
            }
            return true;
        }

        private static bool PublishFile(string filePath)
        {
            Logger.DebugToTag(Library.LogTAG, string.Format("发布文件到服务器:{0}", filePath));
            try
            {
                string relativePath = filePath.Replace(s_targetDir, string.Empty);

                using (Stream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    CPPEI.Coolzon.ServiceProxy.PubServiceRef.PublishSolutionFileRequest request = new ServiceProxy.PubServiceRef.PublishSolutionFileRequest(relativePath, s_solution.Name, s_trancactionId, fileStream);
                    CPPEI.Coolzon.ServiceProxy.PubServiceRef.PublishSolutionFileResponse response = s_pubSerClient.PublishSolutionFile(request);
                    if (!response.IsSuccess)
                    {
                        Logger.ErrorToTag(Library.LogTAG, string.Format("发布方案文件:{0},RelativePath:{1}失败", filePath, relativePath));
                        return false;
                    }
                }
                Logger.DebugToTag(Library.LogTAG, string.Format("发布方案文件:{0},RelativePath:{1}成功", filePath, relativePath));
                return true;
            }
            catch(Exception ex)
            {
                Logger.ErrorToTag(Library.LogTAG, string.Format("发布方案文件:{0}失败,ex:{1}", filePath, ex));
                return false;
            }
        }
        private static bool Prepare()
        {
            try
            {
                CPPEI.Coolzon.ServiceProxy.PubServiceRef.PreparePublishSolutionRequest request = new ServiceProxy.PubServiceRef.PreparePublishSolutionRequest(s_solution.Name);
                CPPEI.Coolzon.ServiceProxy.PubServiceRef.PreparePublishSolutionResponse response = s_pubSerClient.PreparePublishSolution(request);
                if (response.IsSuccess)
                {
                    s_trancactionId = response.TrancactionId;
                    return true;
                }
                return false;
            }
            catch(Exception ex)
            {
                Logger.ErrorToTag(Library.LogTAG, string.Format("准备发布方案文件:{0}失败,ex:{1}", s_solution.Name, ex));
                return false;
            }
        }

        private static bool Commit()
        {
            try
            {
                CPPEI.Coolzon.ServiceProxy.PubServiceRef.CommitPublishSolutionRequest request = new ServiceProxy.PubServiceRef.CommitPublishSolutionRequest(s_solution.Caption,
                    string.Empty,
                    s_solution.RT_Solution.RuntimeVersion,
                    s_solution.ID.ToString(),
                    s_trancactionId,
                    s_solution.SolutionType.ID,
                    s_solution.RT_Solution.Version);
                CPPEI.Coolzon.ServiceProxy.PubServiceRef.CommitPublishSolutionResponse response = s_pubSerClient.CommitPublishSolution(request);
                if (response.IsSuccess)
                {
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                Logger.ErrorToTag(Library.LogTAG, string.Format("提交发布方案完成:{0}失败,ex:{1}", s_solution.Name, ex));
                return false;
            }
        }

        private static bool Cancel()
        {
            try
            {
                CPPEI.Coolzon.ServiceProxy.PubServiceRef.CancelPublishSolutionRequest request = new ServiceProxy.PubServiceRef.CancelPublishSolutionRequest(s_solution.Name, s_trancactionId);
                CPPEI.Coolzon.ServiceProxy.PubServiceRef.CancelPublishSolutionResponse response = s_pubSerClient.CancelPublishSolution(request);
                if (response.IsSuccess)
                {
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                Logger.ErrorToTag(Library.LogTAG, string.Format("撤销发布方案完成:{0}失败,ex:{1}", s_solution.Name, ex));
                return false;
            }
        }
    }
}
